#define FUSE_USE_VERSION 26

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef linux
/* For pread()/pwrite() */
#define _XOPEN_SOURCE 500
#endif

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
#include <sys/time.h>
#include "utils.h"
#include "fatUtiles.h"
#include "cache.h"
#include "pfs.h"

static int pfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	char 				padre[255], nombre[15];
	ST_FILE_ENTRY		fileEntry, parentEntry;
	uint32_t 			primerCluster = 0;

	//printf("Se ejecutó pfs_create :: PATH = %s \n\n\n\n", path);
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_create (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	memset(&fileEntry, 0, sizeof(fileEntry));
	dividirPath(path, padre, nombre);

	getFileEntry(padre, &parentEntry, iSocket);

	fileEntry.dataEntry.attributes = 0x20; //es un archivo
	fileEntry.dataEntry.fileSize = 0;
	fileEntry.dataEntry.fstClusLo = primerCluster & 0x0000FFFF;
	fileEntry.dataEntry.fstClusHi = primerCluster >> 16;
	fileEntry.tieneLongName = 1;

	renombrarFile(nombre, &parentEntry, &fileEntry, iSocket);
	fileEntry.longNameEntry.sequenceN = 0x41; //(0x01+0x40) primera + ultima
	fileEntry.longNameEntry.attributes = 0x0F;

	agregarEntrada(padre, fileEntry, iSocket);

	if ( stPFS.iTamCache != 0 )
		inicializarCache( path );

	sprintf(szAuxiliar, "pfs_create (fin) :: path:%s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_open(const char *path, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_open \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_open (inicio) :: path:%s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	uint32_t 			primerCluster;
	ST_FILE_ENTRY		fileEntry;

	if ( stPFS.iTamCache != 0 )
		inicializarCache( path );

	getFileEntry(path, &fileEntry, iSocket);

	primerCluster = obtenerPrimerCluster( &fileEntry.dataEntry ) ;

	if ( primerCluster == 0 ) {
		sprintf(szAuxiliar, "pfs_open (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}

	sem_wait(&semaforoTablaFAT);
	while ( primerCluster != ULTIMO_CLUSTER ) {
		primerCluster = fatTable[primerCluster];
	}
	sem_post(&semaforoTablaFAT);

	sprintf(szAuxiliar, "pfs_open (fin) :: path:%s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_read(const char *path, char *buf, size_t size, off_t offset,
		    struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_read \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_read (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	//int res = leerArchivo(size, offset, buf, path);




		uint32_t		res;
		ST_FILE_ENTRY	fileEntry;
		ST_CLUSTER 		cluster;
		int				iRtaCache = 0;
		uint32_t 		primerCluster;
		uint32_t 		i, offsetCluster, bytesALeer;
		uint32_t	 	posicionActual, leerDesde;
		uint32_t 		clustersALeer;
		uint32_t 		tamanioALeer;

		sprintf(szAuxiliar, "Lectura sobre el archivo: %s, de tamanio: %d", path, size);
		loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

		getFileEntry(path, &fileEntry, iSocket);

		primerCluster = obtenerPrimerCluster(&fileEntry.dataEntry);

		if(offset > fileEntry.dataEntry.fileSize) {
			cerrarSocketNuevaConexion(iSocket);
			return 0;
		}

		if ((offset + size) > fileEntry.dataEntry.fileSize)
			res = fileEntry.dataEntry.fileSize - offset;
		else
			res = size;

		clustersALeer = ceil(((float)offset+res)/CLUSTER_SIZE)-((float)offset/CLUSTER_SIZE);

		for (i = 0; i < offset/CLUSTER_SIZE; i++){
			sem_wait(&semaforoTablaFAT);
			primerCluster = fatTable[primerCluster];
			sem_post(&semaforoTablaFAT);

			if (primerCluster == ULTIMO_CLUSTER) {
				primerCluster = 0;
				break;
			}
		}

		bytesALeer = res;
		leerDesde = offset;
		posicionActual = 0;

		for (i = 0; i < clustersALeer; i++){

			if ( stPFS.iTamCache != 0 )
				iRtaCache = leerDesdeCache(path, primerCluster, cluster);

			if ( iRtaCache == 0 ) {
				// si no esta en cache
				accederCluster(primerCluster, cluster, LECTURA, iSocket);
				if ( stPFS.iTamCache != 0 )
					escribirEnCache(path, primerCluster, cluster);

			} else {
				printf("trajo el cluster de la cache\n");
			}
			offsetCluster = leerDesde % CLUSTER_SIZE;

			if(bytesALeer > CLUSTER_SIZE - offsetCluster){
				tamanioALeer = CLUSTER_SIZE - offsetCluster;
			}else{
				tamanioALeer = bytesALeer;
			}

			memcpy(&buf[posicionActual], &cluster[offsetCluster], tamanioALeer);

			leerDesde += tamanioALeer;
			posicionActual += tamanioALeer;
			bytesALeer -= tamanioALeer;

			sem_wait(&semaforoTablaFAT);
			primerCluster = fatTable[primerCluster];
			sem_post(&semaforoTablaFAT);
		}







	sprintf(szAuxiliar, "pfs_read (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return res;
}

static int pfs_write(const char *path, const char *buf, size_t size,
		     off_t offset, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_write \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_write (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

//	int res = escribirArchivo(size, offset, buf, path);






	ST_CLUSTER cluster;
	uint32_t primerCluster, res;
	uint32_t i, offsetCluster, bytesAEscribir;
	uint32_t posicionActual, escribirDesde;
	uint32_t clustersAEscribir;
	uint32_t tamanioAEscribir;
	int		iRtaCache = 0;

	ST_FILE_ENTRY fileEntry;
	getFileEntry(path, &fileEntry, iSocket);

	if(offset +size > fileEntry.dataEntry.fileSize) {
		//truncarArchivo(path, offset+size, iSocket);

		/*----------------funcion truncar archivo (inicio)--------------------------*/
		ST_FILE_ENTRY fileEntry;
		off_t tamanio = offset+size;
		uint32_t i, clustersFinales, clustersActuales;
		int32_t clustersDiff;	// negativo si tengo que achicar, positivo si tengo que agrandar
		getFileEntry(path, &fileEntry, iSocket);
		clustersFinales = ceil((float) tamanio / CLUSTER_SIZE);
		clustersActuales = cantidadDeClusters(&fileEntry.dataEntry);
		clustersDiff  = clustersFinales - clustersActuales;
		if (clustersDiff < 0) {
			for (i = 0; i < abs(clustersDiff); i++){
				borrarUltimoCluster(&fileEntry, iSocket);
			}
		}
		else {
			for (i = 0; i < abs(clustersDiff); i++) {
				agregarCluster(&fileEntry, iSocket);
			}
		}
		fileEntry.dataEntry.fileSize = tamanio;
		actualizarEntrada(path, &fileEntry, iSocket);
		/*----------------funcion truncar archivo (fin)--------------------------*/

		getFileEntry(path, &fileEntry, iSocket);
	}

	primerCluster = obtenerPrimerCluster(&fileEntry.dataEntry);
	res = size;
	clustersAEscribir = ceil((((float)offset+res)/CLUSTER_SIZE)-((float)offset/CLUSTER_SIZE));

	for (i = 0; i < offset/CLUSTER_SIZE; i++){
		sem_wait(&semaforoTablaFAT);
		primerCluster = fatTable[primerCluster];
		sem_post(&semaforoTablaFAT);

		if (primerCluster == ULTIMO_CLUSTER) {
			primerCluster = 0;
			break;
		}
	}

	bytesAEscribir = res;
	escribirDesde = offset;
	posicionActual = 0;

	for (i = 0; i < clustersAEscribir; i++) {

		accederCluster(primerCluster, cluster, LECTURA, iSocket);
		offsetCluster = escribirDesde % CLUSTER_SIZE;

		if(bytesAEscribir > CLUSTER_SIZE - offsetCluster)
			tamanioAEscribir = CLUSTER_SIZE - offsetCluster;
		else
			tamanioAEscribir = bytesAEscribir;

		memcpy(&cluster[offsetCluster], &buf[posicionActual], tamanioAEscribir);

		if ( stPFS.iTamCache != 0 )
			iRtaCache = escribirEnCache(path, primerCluster, cluster);

		if ( iRtaCache == 0 ) { // si no escribio en cache
			accederCluster(primerCluster, cluster, ESCRITURA, iSocket);
			printf("se escribio un cluster en cache\n");
		}

		escribirDesde += tamanioAEscribir;
		posicionActual += tamanioAEscribir;
		bytesAEscribir -= tamanioAEscribir;

		sem_wait(&semaforoTablaFAT);
		primerCluster = fatTable[primerCluster];
		sem_post(&semaforoTablaFAT);
	}

	//return res;








	sprintf(szAuxiliar, "pfs_write (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return res;
}

static int pfs_flush(const char *path, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	int32_t i,clusterCacheados;
	//printf("Se ejecutó pfs_flush \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_flush (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	if ( stPFS.iTamCache == 0 ){
		cerrarSocketNuevaConexion(iSocket);
		return 0;
	}

	ST_LISTA_CACHE 		*ptrAuxiliar = buscarEnListaCaches( path );
	clusterCacheados = stPFS.iTamCache / CLUSTER_SIZE;

	sem_wait(&ptrAuxiliar->semaforoDeUso);
	for( i=0; i < clusterCacheados; i++){
		if(ptrAuxiliar->cache[i].numeroCluster != ULTIMO_CLUSTER){
			accederCluster(ptrAuxiliar->cache[i].numeroCluster, ptrAuxiliar->cache[i].bufferCache, ESCRITURA, iSocket);
		}
	}
	sem_post(&ptrAuxiliar->semaforoDeUso);

	sprintf(szAuxiliar, "pfs_flush (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_release(const char *path, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	int32_t i,clusterCacheados;
	//printf("Se ejecutó pfs_release \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_release (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	if ( stPFS.iTamCache == 0 ){
		sprintf(szAuxiliar, "pfs_release (fin) sin cache :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return 0;
	}

	ST_LISTA_CACHE *ptrAuxiliar = buscarEnListaCaches( path );
//	ptrAuxiliar->uContador = ptrAuxiliar->uContador - 1;
//
//	if ( ptrAuxiliar->uContador > 0)
//		return 0;

	clusterCacheados = stPFS.iTamCache / CLUSTER_SIZE;
	sem_wait(&ptrAuxiliar->semaforoDeUso);
	for( i=0; i < clusterCacheados; i++){
		if(ptrAuxiliar->cache[i].numeroCluster != ULTIMO_CLUSTER){
			accederCluster(ptrAuxiliar->cache[i].numeroCluster, ptrAuxiliar->cache[i].bufferCache, ESCRITURA, iSocket);
		}
		else
			break;

	}
	sem_post(&ptrAuxiliar->semaforoDeUso);
	destruirCacheDeArchivo( path );
	sprintf(szAuxiliar, "pfs_release (fin) con cache :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}


static int pfs_truncate(const char *path, off_t size)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_truncate \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_truncate (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	/*int res = truncarArchivo(path, size, iSocket);

	if (res == -1) {
		sprintf(szAuxiliar, "pfs_truncate (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}*/

	/*----------------funcion truncar archivo (inicio)--------------------------*/
	ST_FILE_ENTRY fileEntry;
	off_t tamanio = size;
	uint32_t i, clustersFinales, clustersActuales;
	int32_t clustersDiff;	// negativo si tengo que achicar, positivo si tengo que agrandar
	getFileEntry(path, &fileEntry, iSocket);
	clustersFinales = ceil((float) tamanio / CLUSTER_SIZE);
	clustersActuales = cantidadDeClusters(&fileEntry.dataEntry);
	clustersDiff  = clustersFinales - clustersActuales;
	if (clustersDiff < 0) {
		for (i = 0; i < abs(clustersDiff); i++){
			borrarUltimoCluster(&fileEntry, iSocket);
		}
	}
	else {
		for (i = 0; i < abs(clustersDiff); i++) {
			agregarCluster(&fileEntry, iSocket);
		}
	}
	fileEntry.dataEntry.fileSize = tamanio;
	actualizarEntrada(path, &fileEntry, iSocket);
	/*----------------funcion truncar archivo (fin)--------------------------*/

	sprintf(szAuxiliar, "pfs_truncate (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_ftruncate(const char *path, off_t size, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_ftruncate \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_ftruncate (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	/*int res = truncarArchivo(path, size, iSocket);

	if (res == -1) {
		sprintf(szAuxiliar, "pfs_ftruncate (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}*/

	/*----------------funcion truncar archivo (inicio)--------------------------*/
	ST_FILE_ENTRY fileEntry;
	off_t tamanio = size;
	uint32_t i, clustersFinales, clustersActuales;
	int32_t clustersDiff;	// negativo si tengo que achicar, positivo si tengo que agrandar
	getFileEntry(path, &fileEntry, iSocket);
	clustersFinales = ceil((float) tamanio / CLUSTER_SIZE);
	clustersActuales = cantidadDeClusters(&fileEntry.dataEntry);
	clustersDiff  = clustersFinales - clustersActuales;
	if (clustersDiff < 0) {
		for (i = 0; i < abs(clustersDiff); i++){
			borrarUltimoCluster(&fileEntry, iSocket);
		}
	}
	else {
		for (i = 0; i < abs(clustersDiff); i++) {
			agregarCluster(&fileEntry, iSocket);
		}
	}
	fileEntry.dataEntry.fileSize = tamanio;
	actualizarEntrada(path, &fileEntry, iSocket);
	/*----------------funcion truncar archivo (fin)--------------------------*/

	sprintf(szAuxiliar, "pfs_ftruncate (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_unlink(const char *path)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_unlink \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_unlink (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	int res = borrarArchivo(path, iSocket);

	if (res == -1) {
		sprintf(szAuxiliar, "pfs_unlink (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}

	sprintf(szAuxiliar, "pfs_unlink (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_mkdir(const char *path, mode_t mode)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_mkdir - resultado: --------------------- %s\n\n\n\n", path);
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_mkdir (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	int res = crearDirectorio(path, iSocket);

	sprintf(szAuxiliar, "pfs_mkdir (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return res;
}

static int pfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
		       off_t offset, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_readdir :: PATH = %s \n\n\n\n", path);
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_readdir (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	char 					fileName[14];
	int 					resultado;
	ST_FILE_ENTRY 			file;
	ST_LISTA_FILE_ENTRY 	*listaDirectorio;
	ST_LISTA_FILE_ENTRY 	*p;

	resultado = getFileEntry(path, &file, iSocket);

	if (resultado == 1){
		listaDirectorio = (ST_LISTA_FILE_ENTRY *) obtenerListaDirectorio(&file, iSocket);
	}else{
		sprintf(szAuxiliar, "pfs_readdir (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -ENOENT;
	}

	filler(buf, ".", NULL, 0);
	filler(buf, "..", NULL, 0);

	p = (ST_LISTA_FILE_ENTRY *) listaDirectorio;

	//recorro la lista y voy cargando los directorios/archivos
	while(p != NULL){
		getEntryName(&p->fileEntry, fileName);
		//printf("NAME: %s\n", fileName);
		filler(buf, fileName, NULL,0);
		//printf("file att: %x\n", p->fileEntry.dataEntry.attributes);
		p = p->next;
	}

	liberarListaEntries(listaDirectorio);

	sprintf(szAuxiliar, "pfs_readdir (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_rmdir(const char *path)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_rmdir \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_rmdir (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	int res = borrarDirectorio(path, iSocket);

	if (res == -1) {
		sprintf(szAuxiliar, "pfs_rmdir (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}

	sprintf(szAuxiliar, "pfs_rmdir (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_fgetattr : %s \n\n\n\n", path);
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_fgetattr (inicio) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	int res = 0;
	ST_FILE_ENTRY	file;
	memset(stbuf, 0, sizeof(struct stat));

	if (strncmp(path, "/.Trash", 7) == 0 ) {
		sprintf(szAuxiliar, "pfs_fgetattr (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -ENOENT;
	}

	res = getFileEntry(path, &file, iSocket);
	//printf("reeeeeeeeeeeeeeeessssssssssssss: %i \n", res);

	if( res ) {
		if (file.dataEntry.attributes == 0x10 ) {
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
			//printf("Encontro directorio \n");
		}
		else if ( file.dataEntry.attributes == 0x20) {
			stbuf->st_mode = S_IFREG | 0444;
			stbuf->st_nlink = 1;
			stbuf->st_size = file.dataEntry.fileSize;
			//printf("Encontro archivo chivooooo \n");
		} else {
			//printf("Encontro basuraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \n");
			sprintf(szAuxiliar, "pfs_fgetattr (fin) :: path: %s\0", path);
			loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
			cerrarSocketNuevaConexion(iSocket);
			return -ENOENT;
		}
	}
	else {
		sprintf(szAuxiliar, "pfs_fgetattr (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -ENOENT;
	}

	sprintf(szAuxiliar, "pfs_fgetattr (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_getattr(const char *path, struct stat *stbuf)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_getattr : %s \n\n\n\n", path);
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_getattr (inicio) :: path: %s\0", path);
	loguear( "pfs_getattr.txt", "PFS", "INFO", szAuxiliar);

	int res = 0;
	ST_FILE_ENTRY	file;
	memset(stbuf, 0, sizeof(struct stat));

	if (strncmp(path, "/.Trash", 7) == 0 ) {
		sprintf(szAuxiliar, "pfs_getattr (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -ENOENT;
	}

	res = getFileEntry(path, &file, iSocket);
	//printf("reeeeeeeeeeeeeeeessssssssssssss: %i \n", res);

	if( res ) {
		if (file.dataEntry.attributes == 0x10 ) {
			stbuf->st_mode = S_IFDIR | 0755;
			stbuf->st_nlink = 2;
			//printf("Encontro directorio \n");
		}
		else if ( file.dataEntry.attributes == 0x20) {
			stbuf->st_mode = S_IFREG | 0444;
			stbuf->st_nlink = 1;
			stbuf->st_size = file.dataEntry.fileSize;
			//printf("Encontro archivo chivooooo \n");
		} else {
			//printf("Encontro basuraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \n");
			sprintf(szAuxiliar, "pfs_getattr (fin) :: path: %s\0", path);
			loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
			cerrarSocketNuevaConexion(iSocket);
			return -ENOENT;
		}
	}
	else {
		sprintf(szAuxiliar, "pfs_getattr (fin) :: path: %s\0", path);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -ENOENT;
	}

	sprintf(szAuxiliar, "pfs_fgetattr (fin) :: path: %s\0", path);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static int pfs_rename(const char *from, const char *to)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_rename \n\n\n\n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_rename (inicio) :: from: %s to: %s\0", from, to);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	int res;

	ST_FILE_ENTRY fileEntry, tmpEntry, newEntry;
	getFileEntry(from, &fileEntry, iSocket);

	memcpy(&tmpEntry, &fileEntry, sizeof(ST_FILE_ENTRY));
	tmpEntry.dataEntry.name[0] = 0xE5;
	tmpEntry.longNameEntry.sequenceN = 0xE5;

	actualizarEntrada(from, &tmpEntry, iSocket);		// limpiar entrada anterior

	char parent[255], name[15];
	dividirPath(to, parent, name);

	getFileEntry(parent, &newEntry, iSocket);
	renombrarFile(name, &newEntry, &fileEntry, iSocket);

	agregarEntrada(parent, fileEntry, iSocket);		// agregar nueva entrada

	if (res == -1)	{
		sprintf(szAuxiliar, "pfs_rename (fin) :: from: %s to: %s\0", from, to);
		loguear( "pfsLog.txt", "PFS", "ERROR", szAuxiliar);
		cerrarSocketNuevaConexion(iSocket);
		return -errno;
	}

	sprintf(szAuxiliar, "pfs_rename (fin) :: from: %s to: %s\0", from, to);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

int pfs_access (const char *filename, int how)
{
	int iSocket = generarSocketNuevaConexion();

	//printf("Se ejecutó pfs_access \n");
	char szAuxiliar[100];
	sprintf(szAuxiliar, "pfs_access (inicio y fin) :: filename: %s\0", filename);
	loguear( "pfsLog.txt", "PFS", "INFO", szAuxiliar);

	cerrarSocketNuevaConexion(iSocket);
	return 0;
}

static struct fuse_operations pfs_oper = {
	.create		= pfs_create,	//DONE
	.open		= pfs_open,		//DONE
	.read		= pfs_read,		//DONE
	.write		= pfs_write,	//DONE
	.flush		= pfs_flush,	//DONE
	.release	= pfs_release,	//DONE
	.truncate	= pfs_truncate,	//DONE
	.ftruncate	= pfs_ftruncate,//DONE
	.unlink		= pfs_unlink,	//DONE
	.mkdir		= pfs_mkdir,	//DONE
	.readdir	= pfs_readdir,	//DONE
	.rmdir		= pfs_rmdir,	//DONE
	.fgetattr	= pfs_fgetattr,	//DONE
	.getattr	= pfs_getattr,	//DONE
	.rename		= pfs_rename,	//DONE
	.access		= pfs_access	//DONE
};
